package org.jmc.refmanager.web.wicket.page.validation;

import java.util.Date;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.apache.wicket.PageParameters;
import org.apache.wicket.datetime.markup.html.basic.DateLabel;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.basic.MultiLineLabel;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.jmc.refmanager.domain.model.Change;
import org.jmc.refmanager.domain.model.Change.Operation;
import org.jmc.refmanager.domain.model.OrgUnit;
import org.jmc.refmanager.domain.model.User;
import org.jmc.refmanager.domain.service.ChangeManager;
import org.jmc.refmanager.domain.service.OrgUnitManager;
import org.jmc.refmanager.domain.service.UserManager;
import org.jmc.refmanager.domain.service.exception.BusinessException;
import org.jmc.refmanager.jsr303validators.JSR303FormValidator;
import org.jmc.refmanager.security.SecurityHelper;
import org.jmc.refmanager.util.UpdatesList;
import org.jmc.refmanager.web.wicket.page.template.TemplatePage;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

/**
 */
public class TaskEditMoveOrDeletePage extends TemplatePage {
	@SpringBean(name="orgUnitManager")
	private OrgUnitManager orgUnitManager;

	@SpringBean(name="taskManager")
	private ChangeManager taskManager;
	
	@SpringBean(name="userManager")
	private UserManager userManager;

	/**
	 * @param parameters
	 */
	public TaskEditMoveOrDeletePage(PageParameters parameters) {
		super(parameters);
		initComponents(parameters);
	}

	private void initComponents(final PageParameters parameters) {
		add(new Label("pageTitle", "Validation du changement"));

		final String matricule = SecurityHelper.getAuthentication().getName();

		final Integer taskId = parameters.getAsInteger("id");
		final Change change = taskManager.findById(taskId);

		// Recupere l'objet contenant les changements
		String xmlChanges = change.getObject();

		Serializer serializer = new Persister();
		UpdatesList updates = null;
		try {
			updates = serializer.read(UpdatesList.class, xmlChanges);
		} catch (Exception e) {
			throw new IllegalStateException(
					"Impossible de desérialiser les changements", e);
		}

		// Recupere le service en consultation
		OrgUnit service = orgUnitManager.findById(updates.getServiceId());
		
		final IModel<OrgUnit> serviceModel = new Model<OrgUnit>(service);
		
		ServiceViewForm form = new ServiceViewForm("validateForm", new CompoundPropertyModel<OrgUnit>(serviceModel), change, matricule) {
			private static final long serialVersionUID = 1L;
			
		};

		add(form);
		// Validateur JSR303
        form.add(new JSR303FormValidator());
	}

	/**
	 * 
	 * @param change
	 * @return
	 */
	private OrgUnit getDeletedService(Change change) {
		// Recupere l'objet contenant les changements
		String xmlChanges = change.getObject();

		Serializer serializer = new Persister();
		UpdatesList updates = null;
		try {
			updates = serializer.read(UpdatesList.class, xmlChanges);
		} catch (Exception e) {
			throw new IllegalStateException(
					"Impossible de desérialiser les changements", e);
		}
		
		// Recupere le service e mettre e jour
		OrgUnit deletedService = orgUnitManager.findById(updates.getServiceId());

		deletedService.applySerializedChanges(xmlChanges);
		
		return deletedService;
	}

	private class ServiceViewForm extends Form<OrgUnit> {
		private static final long serialVersionUID = 1L;

		public ServiceViewForm(String id, IModel<OrgUnit> model, final Change change, final String matricule) {
			super(id, model);
			
			OrgUnit service = getModelObject();

			add(new Label("codeUO", new PropertyModel<String>(service, "codeUO")));
			
			String saaOrSao;
			if (service.isSaa()) {
				saaOrSao = "Service administratif";
			} else if (service.isSao()) {
				saaOrSao = "Service opérationnel";
			} else {
				saaOrSao = "n/a";
			}
			
			add(new Label("saaOrSao", saaOrSao));
			add(new Label("libCourt", new PropertyModel<String>(service, "libCourt")));
			add(new Label("parentLibCourt", new PropertyModel<String>(service, "parent.libCourt")));
			add(new Label("codePostal", new PropertyModel<String>(service, "codePostal")));
			add(new Label("commune", new PropertyModel<String>(service, "commune")));
			
			add(DateLabel.forDatePattern("dateFin", 
					new PropertyModel<Date>(service, "dateFin"), "dd/MM/yyyy"));

			String motif = null;
			if (change.getOperation() == Operation.DELETE) {
				motif = getDeletedService(change).getMotifSuppression();
			}
			MultiLineLabel motifLabel = new MultiLineLabel("motif", motif);
			add(motifLabel);

	        Button btnApprove = new Button("btnApprove") {
	        	private static final long serialVersionUID = 1L;

	        	@Override
				public void onSubmit() {
	        		try {
		        		OrgUnit service = ServiceViewForm.this.getModelObject();
	
		        		// Appel de la couche de service
						User approver = userManager.getByMatricule(matricule);
						taskManager.commitAndApprove(change, service, true, approver);
	
						// Affiche le message sur la page redirigee
						getSession().info("Les modifications du service ont été approuvées avec succès.");
						setResponsePage(MyGroupTasksListPage.class);
					} catch (ConstraintViolationException e) {
						error("Les modifications n'ont pas été prises en compte.");
						Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
						for (ConstraintViolation<?> constraintViolation : violations) {
							error(constraintViolation.getMessage());
						}
						setResponsePage(TaskEditMoveOrDeletePage.this);
					}
				}
	        };
	        add(btnApprove);

	        Button btnReject = new Button("btnReject") {
	        	private static final long serialVersionUID = 1L;

	        	@Override
				public void onSubmit() {
	        		try {
		        		// Appel de la couche de service
		        		User approver = userManager.getByMatricule(matricule);
		        		taskManager.commitAndReject(change, approver);
		        		
						// Affiche le message sur la page redirigee
						getSession().info("Les modifications du service ont été rejetées avec succès.");
						setResponsePage(MyGroupTasksListPage.class);
					} catch (ConstraintViolationException e) {
						error("Les modifications n'ont pas été prises en compte.");
						Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
						for (ConstraintViolation<?> constraintViolation : violations) {
							error(constraintViolation.getMessage());
						}
						setResponsePage(TaskEditMoveOrDeletePage.this);
					} catch (BusinessException be) {
						error(be.getMessage());
						setResponsePage(TaskEditMoveOrDeletePage.this);
					}
				}
	        };
	        add(btnReject);

			Button btnCancel = new Button("btnCancel") {
				private static final long serialVersionUID = 1L;
				@Override
				public void onSubmit() {
					// Affiche le message sur la page redirigee
	        		getSession().warn("Aucune modification n'a été réalisée");
					setResponsePage(MyGroupTasksListPage.class);
				}
			};
			// Pas de validation
			btnCancel.setDefaultFormProcessing(false);
			add(btnCancel);
		}
	}
}

